From: Matthieu Gallien Date: Wed, 12 Feb 2025 22:02:57 +0000 (+0100) Subject: try to enforce the windows compatibility as guessed from server X-Git-Tag: archive/raspbian/3.16.7-1_deb13u1+rpi1~1^2~12^2~2^2~50^2~2 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/success/%22http:/www.example.com/cgi/success?a=commitdiff_plain;h=8deb1c57fc6ba242a5d02a893b08b85d3aa5acb8;p=nextcloud-desktop.git try to enforce the windows compatibility as guessed from server for now simple rule to guess if the server has windows naming enforced if windows naming is enforced, we enforce it for new files if not, we do not care for now limited to spaces removal more to come Signed-off-by: Matthieu Gallien --- diff --git a/src/libsync/discovery.cpp b/src/libsync/discovery.cpp index aa6696810..1e325d39d 100644 --- a/src/libsync/discovery.cpp +++ b/src/libsync/discovery.cpp @@ -290,6 +290,7 @@ bool ProcessDirectoryJob::handleExcluded(const QString &path, const Entries &ent const auto hasLeadingOrTrailingSpaces = excluded == CSYNC_FILE_EXCLUDE_LEADING_SPACE || excluded == CSYNC_FILE_EXCLUDE_TRAILING_SPACE || excluded == CSYNC_FILE_EXCLUDE_LEADING_AND_TRAILING_SPACE; + const auto leadingAndTrailingSpacesFilesAllowed = !_discoveryData->_shouldEnforceWindowsFileNameCompatibility || _discoveryData->_leadingAndTrailingSpacesFilesAllowed.contains(_discoveryData->_localDir + path); if (hasLeadingOrTrailingSpaces && (wasSyncedAlready || leadingAndTrailingSpacesFilesAllowed)) { excluded = CSYNC_NOT_EXCLUDED; diff --git a/test/syncenginetestutils.cpp b/test/syncenginetestutils.cpp index 30c6254e5..637c9099c 100644 --- a/test/syncenginetestutils.cpp +++ b/test/syncenginetestutils.cpp @@ -1207,6 +1207,81 @@ void FakeFolder::switchToVfs(QSharedPointer vfs) vfs->start(vfsParams); } +void FakeFolder::enableEnforceWindowsFileNameCompatibility() +{ + syncEngine().account()->setCapabilities(QVariantMap{ + { + "files", + QVariantMap{ + { + "forbidden_filename_basenames", + QStringList{"con", + "prn", + "aux", + "nul", + "com0", + "com1", + "com2", + "com3", + "com4", + "com5", + "com6", + "com7", + "com8", + "com9", + "com¹", + "com²", + "com³", + "lpt0", + "lpt1", + "lpt2", + "lpt3", + "lpt4", + "lpt5", + "lpt6", + "lpt7", + "lpt8", + "lpt9", + "lpt¹", + "lpt²", + "lpt³" + } + }, + { + "forbidden_filename_characters", + QStringList{"\\", + "/", + "<", + ">", + ":", + "\"", + "|", + "?", + "*", + "\\", + "/" + } + }, + { + "forbidden_filename_extensions", + QStringList{" ", + ".", + ".filepart", + ".part", + ".part" + } + }, + { + "forbidden_filenames", + QStringList{"\\", + ".htaccess" + } + } + } + } + }); +} + FileInfo FakeFolder::currentLocalState() { QDir rootDir { _tempDir.path() }; diff --git a/test/syncenginetestutils.h b/test/syncenginetestutils.h index b188a2d00..817a138a5 100644 --- a/test/syncenginetestutils.h +++ b/test/syncenginetestutils.h @@ -559,6 +559,8 @@ public: void switchToVfs(QSharedPointer vfs); + void enableEnforceWindowsFileNameCompatibility(); + [[nodiscard]] OCC::AccountPtr account() const { return _account; } [[nodiscard]] OCC::SyncEngine &syncEngine() const { return *_syncEngine; } [[nodiscard]] OCC::SyncJournalDb &syncJournal() const { return *_journalDb; } diff --git a/test/testlocaldiscovery.cpp b/test/testlocaldiscovery.cpp index 3f4325a6c..43a624eaa 100644 --- a/test/testlocaldiscovery.cpp +++ b/test/testlocaldiscovery.cpp @@ -371,7 +371,10 @@ private slots: void testCreateFileWithTrailingSpaces_localAndRemoteTrimmedDoNotExist_renameAndUploadFile() { FakeFolder fakeFolder{FileInfo{}}; + fakeFolder.enableEnforceWindowsFileNameCompatibility(); + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + const QString fileWithSpaces1(" foo"); const QString fileWithSpaces2(" bar "); const QString fileWithSpaces3("bla "); @@ -459,6 +462,7 @@ private slots: void testCreateLocalPathsWithLeadingAndTrailingSpaces_syncOnSupportingOs() { FakeFolder fakeFolder{FileInfo()}; + fakeFolder.enableEnforceWindowsFileNameCompatibility(); fakeFolder.localModifier().mkdir("A"); QVERIFY(fakeFolder.syncOnce()); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); @@ -541,6 +545,7 @@ private slots: void testCreateFileWithTrailingSpaces_localTrimmedAlsoCreated_dontRenameAutomaticallyAndDontUploadFile() { FakeFolder fakeFolder{FileInfo{}}; + fakeFolder.enableEnforceWindowsFileNameCompatibility(); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); const QString fileWithSpaces(" foo"); const QString fileTrimmed("foo"); diff --git a/test/testsyncengine.cpp b/test/testsyncengine.cpp index 1a1d55971..02f9668cc 100644 --- a/test/testsyncengine.cpp +++ b/test/testsyncengine.cpp @@ -2039,6 +2039,8 @@ private slots: void testCreateFileWithTrailingLeadingSpaces_local_automatedRenameBeforeUpload() { FakeFolder fakeFolder{FileInfo{}}; + fakeFolder.enableEnforceWindowsFileNameCompatibility(); + fakeFolder.syncEngine().setLocalDiscoveryEnforceWindowsFileNameCompatibility(true); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); diff --git a/test/testsyncvirtualfiles.cpp b/test/testsyncvirtualfiles.cpp index e471c5573..f6281ab38 100644 --- a/test/testsyncvirtualfiles.cpp +++ b/test/testsyncvirtualfiles.cpp @@ -835,12 +835,21 @@ private slots: QVERIFY(fakeFolder.syncOnce()); +#if defined Q_OS_WINDOWS QCOMPARE(completeSpy.findItem(fileWithSpaces1)->_status, SyncFileItem::Status::FileNameInvalid); QCOMPARE(completeSpy.findItem(fileWithSpaces2)->_status, SyncFileItem::Status::FileNameInvalid); QCOMPARE(completeSpy.findItem(fileWithSpaces3)->_status, SyncFileItem::Status::FileNameInvalid); QCOMPARE(completeSpy.findItem(fileWithSpaces4)->_status, SyncFileItem::Status::FileNameInvalid); QCOMPARE(completeSpy.findItem(fileWithSpaces5)->_status, SyncFileItem::Status::FileNameInvalid); QCOMPARE(completeSpy.findItem(fileWithSpaces6)->_status, SyncFileItem::Status::FileNameInvalid); +#else + QCOMPARE(completeSpy.findItem(fileWithSpaces1)->_status, SyncFileItem::Status::Success); + QCOMPARE(completeSpy.findItem(fileWithSpaces2)->_status, SyncFileItem::Status::Success); + QCOMPARE(completeSpy.findItem(fileWithSpaces3)->_status, SyncFileItem::Status::Success); + QCOMPARE(completeSpy.findItem(fileWithSpaces4)->_status, SyncFileItem::Status::Success); + QCOMPARE(completeSpy.findItem(fileWithSpaces5)->_status, SyncFileItem::Status::Success); + QCOMPARE(completeSpy.findItem(fileWithSpaces6)->_status, SyncFileItem::Status::Success); +#endif fakeFolder.syncEngine().addAcceptedInvalidFileName(fakeFolder.localPath() + fileWithSpaces1); fakeFolder.syncEngine().addAcceptedInvalidFileName(fakeFolder.localPath() + fileWithSpaces2); @@ -853,12 +862,67 @@ private slots: QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(completeSpy.findItem(fileWithSpaces1)->_status, SyncFileItem::Status::Success); - QCOMPARE(completeSpy.findItem(fileWithSpaces2)->_status, SyncFileItem::Status::Success); - QCOMPARE(completeSpy.findItem(fileWithSpaces3)->_status, SyncFileItem::Status::Success); - QCOMPARE(completeSpy.findItem(fileWithSpaces4)->_status, SyncFileItem::Status::Success); - QCOMPARE(completeSpy.findItem(fileWithSpaces5)->_status, SyncFileItem::Status::Success); - QCOMPARE(completeSpy.findItem(fileWithSpaces6)->_status, SyncFileItem::Status::Success); +#if defined Q_OS_WINDOWS + QCOMPARE(completeSpy.findItem(QStringLiteral("foo"))->_status, SyncFileItem::Status::Success); + QCOMPARE(completeSpy.findItem(QStringLiteral("bar"))->_status, SyncFileItem::Status::Success); + QCOMPARE(completeSpy.findItem(QStringLiteral("bla"))->_status, SyncFileItem::Status::Success); + QCOMPARE(completeSpy.findItem(QStringLiteral("A/foo"))->_status, SyncFileItem::Status::Success); + QCOMPARE(completeSpy.findItem(QStringLiteral("A/bar"))->_status, SyncFileItem::Status::Success); + QCOMPARE(completeSpy.findItem(QStringLiteral("A/bla"))->_status, SyncFileItem::Status::Success); +#endif + } + + void testCreateFileWithTrailingSpaces_acceptAndRejectInvalidFileName_enforceWindowsNamingRules() + { + FakeFolder fakeFolder{ FileInfo() }; + fakeFolder.enableEnforceWindowsFileNameCompatibility(); + setupVfs(fakeFolder); + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + + const QString fileWithSpaces1(" foo"); + const QString fileWithSpaces2(" bar "); + const QString fileWithSpaces3("bla "); + const QString fileWithSpaces4("A/ foo"); + const QString fileWithSpaces5("A/ bar "); + const QString fileWithSpaces6("A/bla "); + + fakeFolder.localModifier().insert(fileWithSpaces1); + fakeFolder.localModifier().insert(fileWithSpaces2); + fakeFolder.localModifier().insert(fileWithSpaces3); + fakeFolder.localModifier().mkdir("A"); + fakeFolder.localModifier().insert(fileWithSpaces4); + fakeFolder.localModifier().insert(fileWithSpaces5); + fakeFolder.localModifier().insert(fileWithSpaces6); + + ItemCompletedSpy completeSpy(fakeFolder); + completeSpy.clear(); + + QVERIFY(fakeFolder.syncOnce()); + + QCOMPARE(completeSpy.findItem(fileWithSpaces1)->_status, SyncFileItem::Status::FileNameInvalid); + QCOMPARE(completeSpy.findItem(fileWithSpaces2)->_status, SyncFileItem::Status::FileNameInvalid); + QCOMPARE(completeSpy.findItem(fileWithSpaces3)->_status, SyncFileItem::Status::FileNameInvalid); + QCOMPARE(completeSpy.findItem(fileWithSpaces4)->_status, SyncFileItem::Status::FileNameInvalid); + QCOMPARE(completeSpy.findItem(fileWithSpaces5)->_status, SyncFileItem::Status::FileNameInvalid); + QCOMPARE(completeSpy.findItem(fileWithSpaces6)->_status, SyncFileItem::Status::FileNameInvalid); + + fakeFolder.syncEngine().addAcceptedInvalidFileName(fakeFolder.localPath() + fileWithSpaces1); + fakeFolder.syncEngine().addAcceptedInvalidFileName(fakeFolder.localPath() + fileWithSpaces2); + fakeFolder.syncEngine().addAcceptedInvalidFileName(fakeFolder.localPath() + fileWithSpaces3); + fakeFolder.syncEngine().addAcceptedInvalidFileName(fakeFolder.localPath() + fileWithSpaces4); + fakeFolder.syncEngine().addAcceptedInvalidFileName(fakeFolder.localPath() + fileWithSpaces5); + fakeFolder.syncEngine().addAcceptedInvalidFileName(fakeFolder.localPath() + fileWithSpaces6); + + completeSpy.clear(); + + QVERIFY(fakeFolder.syncOnce()); + + QCOMPARE(completeSpy.findItem(QStringLiteral("foo"))->_status, SyncFileItem::Status::Success); + QCOMPARE(completeSpy.findItem(QStringLiteral("bar"))->_status, SyncFileItem::Status::Success); + QCOMPARE(completeSpy.findItem(QStringLiteral("bla"))->_status, SyncFileItem::Status::Success); + QCOMPARE(completeSpy.findItem(QStringLiteral("A/foo"))->_status, SyncFileItem::Status::Success); + QCOMPARE(completeSpy.findItem(QStringLiteral("A/bar"))->_status, SyncFileItem::Status::Success); + QCOMPARE(completeSpy.findItem(QStringLiteral("A/bla"))->_status, SyncFileItem::Status::Success); } void testCreateFileWithTrailingSpaces_remoteDontGetRenamedAutomatically()